#include "StdAfx.h"
#include "CalcThreadHolder.h"

#include <boost/bind.hpp>

CCalcThreadHolder::CCalcThreadHolder(CAsteroidOrbitParam::ListPtr &listPtrAsteroidOrbPrm, IApproachHolder *pApproachHolder, OnErrorNotifyInterface *pErrorNotifyInterface)
: m_stoprequested(false)
, m_nMaxThread(boost::thread::hardware_concurrency())
, m_pErrorNotifyInterface(pErrorNotifyInterface)
, m_pApproachHolder(pApproachHolder)
{
	if(m_nMaxThread == 0)
		m_nMaxThread = 1;

	swap(m_listPtrAsteroidOrbPrm, listPtrAsteroidOrbPrm);

	m_pThread = apBoostThread(new boost::thread(boost::bind(&CCalcThreadHolder::do_work, this)));
}

CCalcThreadHolder::~CCalcThreadHolder(void)
{
	Close();
}

void CCalcThreadHolder::Close()
{
	m_stoprequested = true;
	m_pThread->join();

	ListPtr_CApproachCalcThread::iterator it = m_ListWorkThreadPtr.begin();
	ListPtr_CApproachCalcThread::iterator end = m_ListWorkThreadPtr.end();
	for(; it!=end; it++)
	{
		it->Wait();
	}
}

/*
bool CCalcThreadHolder::AppendTrajParam(const TrajParam &trajParam)
{
	boost::mutex::scoped_lock acs(m_mtxInQuery);
	m_listTrajParam.push_back(trajParam);
	return true;
}*/


bool CCalcThreadHolder::IsThreadDone() const
{
	return m_stoprequested;
}

void CCalcThreadHolder::do_work()
{
	int nWaitMilliSec = 30;

	while (!m_stoprequested)
	{
		unsigned nCurrentCountOfThread = 0;
		ListPtr_CApproachCalcThread::iterator it = m_ListWorkThreadPtr.begin();
		ListPtr_CApproachCalcThread::iterator end = m_ListWorkThreadPtr.end();
		ListPtr_CApproachCalcThread::iterator itToDelete = end;
		while( it != end )
		{
			if(it->IsDone(nWaitMilliSec))
			{
				itToDelete = it;
				LPCTSTR strError = it->GetErrorStr();
				if(strError)
				{
					if(m_pErrorNotifyInterface)
					{
						if(m_pErrorNotifyInterface->OnError(strError))
						{
							m_stoprequested = true;
							break;
						}
					}
				}
			}
			else
				nCurrentCountOfThread++;

			it++;
			if(itToDelete != end)
			{
				m_ListWorkThreadPtr.erase(itToDelete);
				itToDelete = end;
			}
		}
		if(m_stoprequested)
			break;
		{
			//boost::mutex::scoped_lock acs(m_mtxInQuery);
			while(nCurrentCountOfThread < m_nMaxThread && m_listPtrAsteroidOrbPrm.size())
			{
				CAsteroidOrbitParam::Ptr pAsterOrbPrm = m_listPtrAsteroidOrbPrm.front();
				CApproachCalcThread *pThread = new CApproachCalcThread(pAsterOrbPrm, m_pApproachHolder);
				m_listPtrAsteroidOrbPrm.pop_front();
				m_ListWorkThreadPtr.push_back(pThread);
				nCurrentCountOfThread ++;
			}
		}

		if(nCurrentCountOfThread == 0)
		{
			boost::posix_time::time_duration waitPeriod;
			waitPeriod = boost::posix_time::milliseconds(nWaitMilliSec * 2);
			boost::this_thread::sleep(waitPeriod);
		}

		{
			//boost::mutex::scoped_lock acs(m_mtxInQuery);
			if(nCurrentCountOfThread == 0 && m_listPtrAsteroidOrbPrm.size() == 0)
				m_stoprequested = true;
		}
	}
}

// =============================================== //
